package com.gcxy.utils;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.util.Date;
import java.util.Objects;

import static com.gcxy.common.StringConstant.SOURCE_PATH_PRIX;

/**
 * @Author lichuandong
 * @Date 2022/3/1
 */
@Slf4j
public class JWTSecurityUtil {

    /**
     * 创建秘钥
     */
    private static final byte[] SECRET = "zdsfot shuyixin should be believed to be young forever".getBytes();

    /**
     * 生成Token
     * @param account
     * @return
     */
    public static String buildJWT(String account,Integer expireTime) throws JOSEException {
        /**
         * 1.创建一个32-byte的密匙
         */
        MACSigner macSigner = new MACSigner(SECRET);
        /**
         * 2. 建立payload 载体
         */
        JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                .expirationTime(new Date(System.currentTimeMillis() + 1000 * 60 * expireTime))
                .claim(SOURCE_PATH_PRIX,account)
                .build();

        /**
         * 3. 建立签名
         */
        SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
        signedJWT.sign(macSigner);

        /**
         * 4. 生成token
         */
        return signedJWT.serialize();
    }

    /**
     * 校验token
     * @param token
     * @return
     */
    public static String checkToken(String token ) throws ParseException, JOSEException {
        SignedJWT jwt;
        try {
            jwt = SignedJWT.parse(token);
        }catch (Exception e){
            throw new RuntimeException("Token 非法");
        }
        JWSVerifier verifier = new MACVerifier(SECRET);
        //校验是否有效
        try {
            if (!jwt.verify(verifier)) {
                throw new RuntimeException("Token 无效");
            }
        }catch (Exception e){
            log.error("token 解密校验失败：{}",e.getMessage());
            throw new RuntimeException("Token 无效");
        }

        //校验超时
        Date expirationTime = jwt.getJWTClaimsSet().getExpirationTime();
        if (new Date().after(expirationTime)) {
            throw new RuntimeException("Token 已过期");
        }

        //获取载体中的数据
        Object account = jwt.getJWTClaimsSet().getClaim(SOURCE_PATH_PRIX);
        //是否有openUid
        if (Objects.isNull(account)){
            throw new RuntimeException("账号为空");
        }
        return account.toString();
    }

}
